package org.javaymw.springboot.service.impl;

import com.baomidou.mybatisplus.mapper.EntityWrapper;
import com.baomidou.mybatisplus.mapper.Wrapper;
import com.baomidou.mybatisplus.service.impl.ServiceImpl;
import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import org.javaymw.springboot.dto.MenuDto;
import org.javaymw.springboot.entity.MenuEntity;
import org.javaymw.springboot.entity.RoleMenuEntity;
import org.javaymw.springboot.mapper.MenuMapper;
import org.javaymw.springboot.mapper.RoleMenuMapper;
import org.javaymw.springboot.mapper.UserMapper;
import org.javaymw.springboot.service.MenuService;
import org.javaymw.springboot.vo.tree.TreeMenuVo;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 描述：
 * <p>
 * Author: 赵新国
 * Date: 2017/10/24 18:36
 */
@Service
public class MenuServiceImpl extends ServiceImpl<MenuMapper, MenuEntity> implements MenuService {

    private static final Logger logger = LoggerFactory.getLogger(MenuServiceImpl.class);

    @Autowired
    private UserMapper userMapper;

    @Autowired
    private MenuMapper menuMapper;

    @Autowired
    private RoleMenuMapper roleMenuMapper;

    @Override
    public Page<MenuDto> getMenuByPage(int pageNum, int pageSize, String searchParam) {
        PageHelper.startPage(pageNum, pageSize);
        Map<String, Object> columnMap = new HashMap<String, Object>(16);
        if (!StringUtils.isEmpty(searchParam)) {
            columnMap.put("name", searchParam);
        }
        Page<MenuEntity> menuEntities = menuMapper.findByPage(columnMap);
        if (menuEntities == null) {
            return null;
        }
        Page<MenuDto> menuDtos = new Page<MenuDto>();
        for (MenuEntity menuEntity : menuEntities) {
            MenuDto menuDto = new MenuDto();
            BeanUtils.copyProperties(menuEntity, menuDto);
            // 根据菜单上级ID，查询菜单信息
            MenuEntity entity = new MenuEntity();
            entity.setId(menuDto.getpId());
            MenuEntity resultEntity = menuMapper.selectOne(entity);
            if (resultEntity != null) {
                menuDto.setpName(resultEntity.getName());
            }
            menuDtos.add(menuDto);
        }
        return toDto(menuEntities, menuDtos);
    }

    @Override
    public List<TreeMenuVo> getLeftMenuByTree(String name, Long parentId, Long id) {
        List<MenuEntity> menuEntities = menuMapper.getLeftMenuByIds(name, parentId, id);
        if (menuEntities.isEmpty()) return null;
        List<TreeMenuVo> treeMenuVos = getTreeMenuVos(menuEntities);
        return treeMenuVos;
    }

    @Override
    public List<TreeMenuVo> getMenuByTree(String name, Long parentId, Long id) {
        Wrapper<MenuEntity> wrapper = new EntityWrapper<MenuEntity>();
        if (!StringUtils.isEmpty(name)) {
            wrapper.eq("name", name);
        }
        if (parentId != null) {
            wrapper.ne("pid", parentId);
        }
        List<MenuEntity> menuEntities = menuMapper.selectList(wrapper);
        if (menuEntities.isEmpty()) return null;
        List<TreeMenuVo> treeMenuVos = getTreeMenuVos(menuEntities);
        return treeMenuVos;
    }

    private List<TreeMenuVo> getTreeMenuVos(List<MenuEntity> menuEntities) {
        /**
         * List to Tree
         */
        List<TreeMenuVo> menuVos = new ArrayList<TreeMenuVo>();
        for (MenuEntity menuEntity : menuEntities) {
            TreeMenuVo treeMenuVo = new TreeMenuVo();
            BeanUtils.copyProperties(menuEntity, treeMenuVo);
            menuVos.add(treeMenuVo);
        }

        List<TreeMenuVo> treeMenuVos = new ArrayList<TreeMenuVo>();
        for (TreeMenuVo treeMenuVo1 : menuVos) {
            boolean mark = false;
            for (TreeMenuVo treeMenuVo2 : menuVos) {
                if (treeMenuVo1.getpId() != null && treeMenuVo1.getpId().equals(treeMenuVo2.getId())) {
                    mark = true;
                    if (treeMenuVo2.getChildren() == null) {
                        treeMenuVo2.setChildren(new ArrayList<TreeMenuVo>());
                    }
                    treeMenuVo2.getChildren().add(treeMenuVo1);
                    break;
                }
            }
            if (!mark) {
                treeMenuVos.add(treeMenuVo1);
            }
        }

        return treeMenuVos;
    }

    @Override
    public Integer save(MenuDto menuDto) {
        MenuEntity menuEntity = new MenuEntity();
        BeanUtils.copyProperties(menuDto, menuEntity);
        return menuMapper.insert(menuEntity);
    }

    @Override
    public MenuDto getMenuById(Long id) {
        MenuEntity menuEntity = menuMapper.selectById(id);
        if (menuEntity == null) {
            return null;
        }
        MenuDto menuDto = new MenuDto();
        BeanUtils.copyProperties(menuEntity, menuDto);
        return menuDto;
    }

    @Override
    public Integer update(MenuDto menuDto) {
        MenuEntity menuEntity = new MenuEntity();
        BeanUtils.copyProperties(menuDto, menuEntity);
        Wrapper<MenuEntity> wrapper = new EntityWrapper<>();
        wrapper.eq("id", menuDto.getId());
        return menuMapper.update(menuEntity, wrapper);
    }

    @Override
    public MenuDto getMenuByParentId(Long parentId) {
        MenuEntity entity = new MenuEntity();
        entity.setId(parentId);
        MenuEntity menuEntity = menuMapper.selectOne(entity);
        if (menuEntity == null) {
            return null;
        }
        MenuDto menuDto = new MenuDto();
        BeanUtils.copyProperties(menuEntity, menuDto);
        return menuDto;
    }

    @Override
    public List<MenuDto> getMenusByRoleId(Long roleId) {
        Wrapper<RoleMenuEntity> wrapper = new EntityWrapper<>();
        wrapper.eq("role_id", roleId);
        List<RoleMenuEntity> roleMenuEntities = roleMenuMapper.selectList(wrapper);
        if (!roleMenuEntities.isEmpty()) {
            List<Long> menuIds = new ArrayList<>(roleMenuEntities.size());
            roleMenuEntities.stream().forEach(roleMenuEntity -> menuIds.add(roleMenuEntity.getMenuId()));
            Wrapper<MenuEntity> menuWrapper = new EntityWrapper<>();
            menuWrapper.in("id", menuIds);
            List<MenuEntity> menuEntities = menuMapper.selectList(menuWrapper);
            if (!menuEntities.isEmpty()) {
                List<MenuDto> menuDtos = new ArrayList<>();
                menuEntities.stream().forEach(menuEntity -> {
                    MenuDto menuDto = new MenuDto();
                    BeanUtils.copyProperties(menuEntity, menuDto);
                    menuDtos.add(menuDto);
                });
                return menuDtos;
            }
        }
        return null;
    }

    @Override
    public MenuDto getParentMenusById(Long id) {
        MenuEntity menuEntity = menuMapper.selectById(id);
        if (menuEntity != null) {
            MenuEntity pMenuEntity = menuMapper.selectById(menuEntity.getpId());
            if (pMenuEntity != null) {
                MenuDto menuDto = new MenuDto();
                BeanUtils.copyProperties(pMenuEntity, menuDto);
                return menuDto;
            }
        }
        return null;
    }

    @Override
    public List<MenuDto> findAll() {
        List<MenuEntity> menuEntities = menuMapper.selectList(new EntityWrapper<>());
        if (!menuEntities.isEmpty()) {
            List<MenuDto> menuDtos = new ArrayList<>();
            menuEntities.stream().forEach(menuEntity -> {
                MenuDto menuDto = new MenuDto();
                BeanUtils.copyProperties(menuEntity, menuDto);
                menuDtos.add(menuDto);
            });
            return menuDtos;
        }
        return null;
    }

    @Override
    public List<MenuDto> loadUserMenus(Map<String, Object> map) {
        List<MenuEntity> menuEntities = menuMapper.loadUserMenus(map);
        if (!menuEntities.isEmpty()) {
            List<MenuDto> menuDtos = new ArrayList<>();
            menuEntities.stream().forEach(menuEntity -> {
                MenuDto menuDto = new MenuDto();
                BeanUtils.copyProperties(menuEntity, menuDto);
                menuDtos.add(menuDto);
            });
            return menuDtos;
        }
        return null;
    }

    private Page<MenuDto> toDto(Page<MenuEntity> menuEntities, Page<MenuDto> menuDtos) {
        BeanUtils.copyProperties(menuEntities, menuDtos);
        return menuDtos;
    }

}
